﻿using System;

namespace IceCS.DataStructure.Helpers
{
    /// <summary>
    /// 控制器帮助类
    /// </summary>
    public static class ConsoleHelper
    {
        /// <summary>
        /// 设置控制台窗口的一种样式
        /// </summary>
        public static void SetConsoleStyle1(string consoleTitle)
        {
            Console.WindowWidth = 70;
            Console.WindowHeight = 26;
            Console.BufferWidth = 70;
            Console.BufferHeight = 26;
            Console.Title = consoleTitle;
            Console.BackgroundColor = ConsoleColor.Black;
            Console.ForegroundColor = ConsoleColor.Green;

        }
        #region 泛型基础方法
        /// <summary>
        /// 获取符合条件的输入结果
        /// </summary>
        /// <typeparam name="T">T一般为 string ,int 类型</typeparam>
        /// <param name="tips">输入提示内容</param>
        /// <param name="conditionList">预期传入参数列表</param>
        /// <param name="predicate">(inputVal,conditionItem)，第一个参数为输入值，第二个参数为当前遍历的预期传入参数，返回一个布尔值表示入参是否符合条件</param>
        /// <param name="errorTips">输入错误提示内容</param>
        /// <returns></returns>
        public static T GetRightInput<T>(string tips, T[] conditionList, Func<T, T, bool> predicate, string errorTips = "输入数据错误，请重新输入")
        {
            Console.WriteLine(tips);
            while (true)
            {
                var input = Console.ReadLine();
                if (string.IsNullOrWhiteSpace(input))
                {
                    Console.WriteLine(errorTips);
                    continue;
                }

                try
                {
                    T inputVal = (T)Convert.ChangeType(input, typeof(T));
                    foreach (var conditionItem in conditionList)
                    {
                        if (predicate(inputVal, conditionItem))
                        {
                            return conditionItem;
                        }
                    }
                }
                catch
                {
                    Console.WriteLine(errorTips);
                    continue;
                }

                Console.WriteLine(errorTips);
            }
        }

        /// <summary>
        /// 获取符合条件的输入结果
        /// </summary>
        /// <typeparam name="T">T一般为 string ,int 类型</typeparam>
        /// <param name="tips">输入提示内容</param>
        /// <param name="predicate">(inputVal)，传入参数为输入值,返回一个布尔值表示入参是否符合条件</param>
        /// <param name="errorTips">输入错误提示内容</param>
        /// <returns></returns>
        public static T GetRightInput<T>(string tips, Func<T, bool> predicate, string errorTips = "输入数据错误，请重新输入")
        {
            Console.WriteLine(tips);
            while (true)
            {
                var input = Console.ReadLine();
                if (string.IsNullOrWhiteSpace(input))
                {
                    Console.WriteLine(errorTips);
                    continue;
                }

                try
                {
                    T inputVal = (T)Convert.ChangeType(input, typeof(T));
                    if (predicate(inputVal))
                    {
                        return inputVal;
                    }
                }
                catch
                {
                    Console.WriteLine(errorTips);
                    continue;
                }

                Console.WriteLine(errorTips);
            }
        }
        #endregion

        /// <summary>
        /// 获取符合条件的字符串输入
        /// </summary>
        /// <param name="tips">提示内容</param>
        /// <param name="conditionList">符合条件参数列表</param>
        /// <param name="errorTips">错误提示</param>
        /// <returns></returns>
        public static string GetRightInputString(string tips, string[] conditionList, string errorTips = "输入文本错误，请重新输入")
        {
            var result = GetRightInput(tips, conditionList, (inputVal, conditionItem) => inputVal == conditionItem, errorTips);
            return result;
        }

        /// <summary>
        /// 判断用户输入的是Yes还是No，如果是yes返回true，no返回false
        /// </summary>
        /// <param name="conditionList">符合条件参数列表</param>
        /// <param name="errorTips">错误提示</param>
        /// <returns></returns>
        public static bool GetRightInputStringYN(string errorTips = "输入文本错误，请重新输入")
        {
            string tips = "请输入 Y/N 或者 Yes/No";
            var inputVal = GetRightInputString(tips, new string[] { "Y", "y", "Yes", "yes", "N", "n", "No", "no" }, errorTips);
            var result = inputVal.ToLower().Contains("y");
            return result;
        }

        /// <summary>
        /// 获取符合条件的字符串输入
        /// </summary>
        /// <param name="tips">提示内容</param>
        /// <param name="predicate">根据输入值进行判断</param>
        /// <param name="errorTips">错误提示</param>
        /// <returns></returns>
        public static string GetRightInputString(string tips, Func<string, bool> predicate, string errorTips = "输入文本错误，请重新输入")
        {
            var result = GetRightInput(tips, predicate, errorTips);
            return result;
        }

        /// <summary>
        /// 获取符合条件的数字输入
        /// </summary>
        /// <param name="tips">提示内容</param>
        /// <param name="conditionList">符合条件参数列表</param>
        /// <param name="errorTips">错误提示</param>
        /// <returns></returns>
        public static int GetRightInputNumber(string tips, int[] conditionList, string errorTips = "输入数字错误，请重新输入")
        {
            var result = GetRightInput(tips, conditionList, (inputVal, conditionItem) => inputVal == conditionItem, errorTips);
            return result;
        }

        /// <summary>
        /// 获取符合条件的数字输入
        /// </summary>
        /// <param name="tips">提示内容</param>
        /// <param name="predicate">根据输入值进行判断</param>
        /// <param name="errorTips">错误提示</param>
        /// <returns></returns>
        public static int GetRightInputNumber(string tips, Func<int, bool> predicate, string errorTips = "输入数字错误，请重新输入")
        {
            var result = GetRightInput(tips, predicate, errorTips);
            return result;
        }

        /// <summary>
        /// 获取符合条件的数字输入
        /// </summary>
        /// <param name="tips">提示内容</param>
        /// <param name="minValue">输入数字最小值，包含最小值</param>
        /// <param name="maxValue">输入数字最大值，包含最大值</param>
        /// <param name="errorTips">错误提示</param>
        /// <returns></returns>
        public static int GetRightInputNumber(string tips, int minValue, int maxValue, string errorTips = "输入数字超出范围，请重新输入")
        {
            var result = GetRightInputNumber(tips, inputVal => inputVal >= minValue && inputVal <= maxValue, errorTips);
            return result;
        }

        /// <summary>
        /// 确保输入的是数字,且大于等于最小值
        /// </summary>
        /// <param name="tips">提示内容</param>
        /// <param name="minValue">最小值</param>
        /// <returns></returns>
        public static int GetRightInputNumberGreatThanMinValue(string tips, int minValue = 0)
        {
            string errorTips = "输入数字小于最小值，请重新输入";
            return GetRightInputNumber(tips, inputVal => inputVal >= minValue, errorTips);
        }

        /// <summary>
        /// 确保输入的是数字,且小于等于最大值
        /// </summary>
        /// <param name="tips">提示内容</param>
        /// <param name="maxValue">最大值</param>
        /// <returns></returns>
        public static int GetRightInputNumberLessThanMaxValue(string tips, int maxValue = 10)
        {
            string errorTips = "输入数字大于最大值，请重新输入";
            return GetRightInputNumber(tips, inputVal => inputVal <= maxValue, errorTips);
        }

        /// <summary>
        /// 获取列表项中选中的项编号（从1开始）
        /// </summary>
        /// <param name="texts"></param>
        /// <returns></returns>
        public static int GetSingleSelectedItemIndex(string[] texts)
        {
            Console.WriteLine("列表");
            for (int i = 0; i <texts.Length; i++)
            {
                var text = texts[i];
                Console.WriteLine($"[{i+1}] {text}");
            }
            return GetRightInputNumber("请选择",1,texts.Length);
        }
    }
}